package com.hc.shiro;

import com.hc.domain.Permission;
import com.hc.domain.Role;
import com.hc.domain.User;
import com.hc.service.PermissionService;
import com.hc.service.RoleService;
import com.hc.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Set;

/**
 * 自定义Realm
 */
public class UserRealm extends AuthorizingRealm {
    @Resource
    private UserService userService;
    @Resource
    private RoleService roleService;
    @Resource
    private PermissionService permissionService;

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("===================doGetAuthenticationInfo=============================");
        //模拟从数据库中获取用户名密码
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;

        User user = userService.getUserByUsername(userToken.getUsername());
        //用户不存在
        if (null == user) {
            return null; //抛出异常UnknownAccountException
        }
        // 用户被锁定
        if (user.getLocked()) {
            throw new LockedAccountException("该用户已被锁定,暂时无法登录！");
        }

        // 获取用户的盐值
        //ByteSource salt = ByteSource.Util.bytes(user.getSalt());
        MyByteSource salt = new MyByteSource(user.getSalt());

        //不能自己做密码认证，系统会自己做
        // 第一个参数为用户信息，方便授权时查找用户的权限
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), salt, getName());
        return simpleAuthenticationInfo;
    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("===================doGetAuthorizationInfo=============================");
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();

        // 查询数据库，获取用户的角色信息（包含在用户对象中）
        Set<Role> roles = roleService.getRolesByUserId(user.getId());

        //授权角色
        if (!CollectionUtils.isEmpty(roles)) {
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            roles.forEach(role -> {
                simpleAuthorizationInfo.addRole(role.getCode()); //基于角色的权限管理
                // 授权权限
                Set<Permission> permissions = permissionService.getPermissionsByRoleId(role.getId());
                if (!CollectionUtils.isEmpty(permissions)) {
                    permissions.forEach(permission -> {
                        simpleAuthorizationInfo.addStringPermission(permission.getCode()); //基于资源的权限管理
                    });
                }
            });
            return simpleAuthorizationInfo;
        }
        return null;
    }

}
